package cn.iocoder.yudao.module.ad.order.service;

import cn.iocoder.yudao.framework.business.basic.dao.query.CoreQueryWrapper;
import cn.iocoder.yudao.framework.business.basic.dao.repository.SerialNoRedisRepository;
import cn.iocoder.yudao.framework.business.order.service.AppOrderBaseService;
import cn.iocoder.yudao.framework.common.exception.Assertions;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.ad.order.dal.dataobject.AdPlanOrderDO;
import cn.iocoder.yudao.module.ad.order.dal.mysql.AdPlanOrderMapper;
import cn.iocoder.yudao.module.ad.order.vo.AdPlanOrderSubmitDTO;
import cn.iocoder.yudao.module.ad.order.vo.AppAdPlanOrderVO;
import cn.iocoder.yudao.module.ad.plan.dal.dataobject.AdPlanDO;
import cn.iocoder.yudao.module.ad.plan.dal.mysql.AdPlanMapper;
import cn.iocoder.yudao.module.ad.plan.service.AppAdPlanService;
import cn.iocoder.yudao.module.api.pay.bill.PayBillApi;
import cn.iocoder.yudao.module.api.pay.bill.dto.PayBillCreateDTO;
import cn.iocoder.yudao.module.api.pay.bill.enums.BillCategoryEnum;
import cn.iocoder.yudao.module.api.pay.bill.enums.BillTypeEnum;
import cn.iocoder.yudao.module.api.pay.order.PayOrderApi;
import cn.iocoder.yudao.module.api.pay.order.dto.PayOrderCreateDTO;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import static cn.iocoder.yudao.module.api.ad.ConfigConstants.AD_PLAN_ORDER_NO_PREFIX;

/**
 * 广告投放订单 Service 实现类
 *
 * @author 山野羡民
 */
@Slf4j
@Service
@Validated
public class AppAdPlanOrderServiceImpl extends AppOrderBaseService<AdPlanOrderDO, AppAdPlanOrderVO, AdPlanOrderSubmitDTO> implements AppAdPlanOrderService {
    @Resource
    private AdPlanOrderMapper adPlanOrderMapper;
    @Resource
    private AdPlanMapper adPlanMapper;

    @Resource
    private SerialNoRedisRepository serialNoRedisRepository;

    @Resource
    private AppAdPlanService appAdPlanService;

    @Resource
    private PayOrderApi payOrderApi;
    @Resource
    private PayBillApi payBillApi;

    @Nonnull
    @Override
    protected AdPlanOrderDO onOrderCreateBefore(@Nonnull AdPlanOrderSubmitDTO reqVO, @Nonnull Long userId) {
        // 校验存在
        AdPlanDO planDO = adPlanMapper.selectById(reqVO.getPlanId());
        Assertions.notNull(planDO, "广告投放计划不存在");
        // 构建订单信息
        AdPlanOrderDO order = new AdPlanOrderDO();
        order.setUserId(userId);
        order.setPlanId(planDO.getId());
        order.setPrice(planDO.getBudgetPrice());
        order.setSnapshot(JsonUtils.toJsonString(planDO));
        order.setTradeNo(serialNoRedisRepository.generateNo(AD_PLAN_ORDER_NO_PREFIX));
        order.setNote("投放广告预算【%s元】，预期曝光【%s次】".formatted(MoneyUtils.fenToYuanStr(planDO.getBudgetPrice()), planDO.getExceptExposureCount()));
        return order;
    }

    @Async
    @Override
    public void createPayOrder(@Nonnull AdPlanOrderDO order) {
        PayOrderCreateDTO createReqDTO = new PayOrderCreateDTO();
        createReqDTO.setTradeNo(order.getTradeNo());
        createReqDTO.setSubject(BillTypeEnum.PAY_AD_PLAN.getName());
        createReqDTO.setBody(order.getNote());
        createReqDTO.setPrice(order.getPrice());
        payOrderApi.createOrder(createReqDTO);
    }

    @Override
    protected void onPaidAfter(AdPlanOrderDO order) {
        appAdPlanService.updateWhenPaid(order.getTradeNo(), order.getUserId(), order.getPlanId());
        payBillApi.expendAsync(new PayBillCreateDTO()
                .setUserId(order.getUserId())
                .setCategory(BillCategoryEnum.MONEY)
                .setType(BillTypeEnum.PAY_AD_PLAN)
                .setNumber(1d * order.getPrice())
                .setMark(order.getNote())
                .setRelateId(order.getTradeNo())
                .setExtendField("{\"planId\":\"%s\"}".formatted(order.getPlanId())));
    }

    @Override
    public PageResult<AppAdPlanOrderVO> getPage(Integer pageNo, Integer pageSize, Long userId) {
        CoreQueryWrapper<AdPlanOrderDO> wrapper = new CoreQueryWrapper<>();
        wrapper.eq("user_id", userId);
        PageResult<AdPlanOrderDO> page = adPlanOrderMapper.selectPage(pageNo, pageSize, wrapper);
        return BeanUtils.toBean(page, AppAdPlanOrderVO.class);
    }

    @Override
    protected AdPlanOrderMapper getInjectedMapper() {
        return adPlanOrderMapper;
    }

}